#include "windowHelp4gl.h"
#include <Windowsx.h>
#include <stdio.h>
#include <string>

#include "../common.h"
#include "../ui/input/keyboradinputmanager.h"
#include "../ui/input/mouseinputmanager.h"


KeyBoardInputManager* keyboardInput = 0;
MouseInputManager* mouseInput = 0;

LRESULT CALLBACK WindowHelp4GLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
     switch (msg)
    {
        case WM_CREATE:
            // Initialize the window.
            printf("WM_CREATE hwnd:%d\n",(int)hwnd);
            return DefWindowProc(hwnd, msg, wParam, lParam);
        case WM_PAINT:
            // Paint the window's client area.
            //printf("WM_PAINT hwnd:%d\n",(int)hwnd);
            return DefWindowProc(hwnd, msg, wParam, lParam);

        case WM_SIZE:
            // Set the size and position of the window.
            printf("WM_SIZE hwnd:%d\n",(int)hwnd);
            return DefWindowProc(hwnd, msg, wParam, lParam);
        case WM_DESTROY:
            {
                // Clean up window-specific data objects.
                printf("WM_DESTROY hwnd:%d\n",(int)hwnd);
                PostQuitMessage(0);
                return 0;
            }
        case WM_LBUTTONDOWN:
            {
                //printf("WM_LBUTTONDOWN hwnd:%d\n",(int)hwnd);
                int x = GET_X_LPARAM(lParam);
                int y = GET_Y_LPARAM(lParam);

                mouseInput->checkAllClickable(x,y);

                return 0;
            }
        case WM_KEYDOWN:
            {
                keyboardInput->keyDown(wParam,lParam);
                return DefWindowProc(hwnd, msg, wParam, lParam);
            }
        case WM_KEYUP:
            {
                keyboardInput->keyUp(wParam,lParam);
                return DefWindowProc(hwnd, msg, wParam, lParam);
            }
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

WindowHelp4GL* WindowHelp4GL::WindowHelp4GLInstance = 0;

WindowHelp4GL::WindowHelp4GL():MyRegisterlpszClassName("WindowHelp4GLClassName")
{
    m_hdc = 0;
    m_hwnd = 0;
    m_glrc = 0;
    memset(m_data,0,sizeof(EveryData)*UserDataNumber);

    WindowHelp4GLInstance = this;

    KeyBoardInputManager::createInstance();
    MouseInputManager::createInstance();
    keyboardInput = KeyBoardInputManager::getInstance();
    mouseInput = MouseInputManager::getInstance();
}

WindowHelp4GL::~WindowHelp4GL()
{
    if(m_glrc)
    {
        //printf("delete glrc\n");
        wglDeleteContext(m_glrc);
        m_glrc = 0;
    }

    if(m_hdc)
    {
        //printf("delete dc\n");
        ReleaseDC(m_hwnd,m_hdc);
        m_hdc = 0;
    }

    if(m_hwnd)
    {
        if(IsWindow(m_hwnd))
            DestroyWindow(m_hwnd);
    }

    if(this == getInstance())
    {
        WindowHelp4GLInstance = 0;
    }

    KeyBoardInputManager::releaseInstance();
    MouseInputManager::releaseInstance();
    keyboardInput = 0;
    mouseInput = 0;
}

ATOM WindowHelp4GL::MyRegisterClass(HINSTANCE hinstance,LPCTSTR className,LPCTSTR menuName)
{
    WNDCLASSEX wcex;
    wcex.cbSize         =   sizeof(WNDCLASSEX);
    wcex.style          =   CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc    =   WindowHelp4GLWndProc;
    wcex.cbClsExtra     =   0;
    wcex.cbWndExtra     =   0;
    wcex.hInstance      =   hinstance;
    wcex.hIcon          =   LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor        =   LoadCursor(NULL,IDC_ARROW);
    wcex.hbrBackground  =   (HBRUSH)GetStockObject(WHITE_BRUSH);
    wcex.lpszMenuName   =   menuName;
    wcex.lpszClassName  =   className;
    wcex.hIconSm        =   NULL;

    return RegisterClassEx(&wcex);
}

HWND WindowHelp4GL::MyCreateWindow(HINSTANCE hinstance,LPCTSTR className,LPCTSTR title,
                    int pos_x ,int pos_y,int width,int height)
{
    RECT winRect;
    winRect.left = pos_x;
    winRect.right = pos_x + width;
    winRect.top = pos_y;
    winRect.bottom = pos_y + height;

    DWORD windowStyle = WS_OVERLAPPEDWINDOW;
    DWORD windowExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

    AdjustWindowRectEx(&winRect,windowStyle,FALSE,windowExStyle);

    return CreateWindowEx(
        windowExStyle,
        className,            // name of window class
        title,            // title-bar string
        windowStyle,    // top-level window
        winRect.left,          // default horizontal position
        winRect.top,       // default vertical position
        winRect.right - winRect.left,       // default width
        winRect.bottom - winRect.top,       // default height
        (HWND) NULL,         // no owner window
        (HMENU) NULL,        // use class menu
        hinstance,           // handle to application instance
        (LPVOID) NULL);      // no window-creation data
}

HGLRC WindowHelp4GL::initPixelformat4GL(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
    /* set the pixel format for the DC */
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW |
                  PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int  iPixelFormat;
    // get the best available match of pixel format for the device context
    iPixelFormat = ChoosePixelFormat(hdc, &pfd);

    if(!iPixelFormat)
        return 0;
    // make that the pixel format of the device context
    if( FALSE == SetPixelFormat(hdc, iPixelFormat, &pfd))
        return 0;

    HGLRC hglrc =  wglCreateContext(hdc);
    if(!hglrc)
        return 0;

    wglMakeCurrent(hdc, hglrc);
	return hglrc;
}

bool WindowHelp4GL::createGLWindow(HINSTANCE hinstance,LPCTSTR title,int pos_x,int pos_y,int width,int height)
{
    if(0 == MyRegisterClass(hinstance,MyRegisterlpszClassName))
    {
        printf("MyRegisterClass Error:%d\n",(unsigned int)GetLastError());
        return false;
    }

    m_hwnd = MyCreateWindow(hinstance,MyRegisterlpszClassName,title,pos_x,pos_y,width,height);
    if(0 == m_hwnd)
    {
        printf("MyCreateWindow Error:%d\n",(unsigned int)GetLastError());
        return false;
    }

    m_hdc  = GetDC(m_hwnd);
    if(0 == m_hdc)
    {
        printf("GetDC Error:%d\n",(unsigned int)GetLastError());
        return false;
    }

    m_glrc = initPixelformat4GL(m_hdc);
    if(0 == m_glrc)
    {
        printf("initPixelformat4GL Error:%d\n",(unsigned int)GetLastError());
        return false;
    }

    ShowWindow(m_hwnd,SW_SHOW);
	SetForegroundWindow(m_hwnd);
	SetFocus(m_hwnd);

	resizeGLScene(width,height);
	initGLParameters();

    return true;
}

void WindowHelp4GL::resizeGLScene(const GLsizei width,const GLsizei height)
{
    GLsizei w = width;
    GLsizei h = height;
    if(h == 0) h = 1;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,w,h,0,0,1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void WindowHelp4GL::initGLParameters()
{
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    glClearColor(0.0f,0.0f,0.0f,0.5f);
}
